import base64
import cv2
import json
import os
import uuid
from flask import Blueprint, request, current_app
from models.models import ObjectDetection, db
from utils.helpers import api_response

detection_bp = Blueprint('detection', __name__)

@detection_bp.route('', methods=['POST'])
def detect_image():
    """
    图像目标检测
    ---
    tags:
      - 目标检测
    parameters:
      - name: image
        in: formData
        type: file
        required: true
        description: 要检测的图片文件
    responses:
      200:
        description: 检测完成
        schema:
          type: object
          properties:
            code:
              type: integer
              example: 200
            message:
              type: string
              example: "检测成功"
            data:
              type: object
              properties:
                detection_id:
                  type: integer
                  description: 检测记录ID
                result_image:
                  type: string
                  description: 带有检测框的结果图像(Base64)
                object_count:
                  type: integer
                  description: 检测到的目标数量
                detection_data:
                  type: object
                  description: 详细的检测结果数据
      400:
        description: 参数错误
      500:
        description: 服务器内部错误
    """
    try:
        if 'image' not in request.files:
            return api_response(message="未上传图片", code=400, status_code=400)
            
        file = request.files['image']
        if file.filename == '':
            return api_response(message="空文件名", code=400, status_code=400)
            
        # 生成唯一文件名
        filename = f"{uuid.uuid4().hex}.jpg"
        upload_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
        result_path = os.path.join(current_app.config['RESULT_FOLDER'], filename)
        
        # 保存原始图片
        current_app.logger.info(f"保存原始图片到: {upload_path}")
        file.save(upload_path)
        
        # 使用YOLOv8进行检测
        result, detection_info = current_app.yolo_service.detect(upload_path, current_app.config['YOLO_CLASS_MAPPING'])
        
        # 保存结果图片
        result_img = result.plot()
        current_app.logger.info(f"保存结果图片到: {result_path}")
        success = cv2.imwrite(result_path, result_img)
        
        if not success:
            current_app.logger.error("结果图片保存失败")
            raise RuntimeError("无法保存结果图片")
            
        # 保存结果图片后添加验证
        if not os.path.exists(result_path):
            current_app.logger.error(f"结果文件未生成: {result_path}")
            raise FileNotFoundError("结果图片保存失败")
            
        current_app.logger.info(f"验证文件存在: {result_path} (大小: {os.path.getsize(result_path)} bytes)")
        
        # 将结果图片转为base64
        _, buffer = cv2.imencode('.jpg', result_img)
        result_base64 = base64.b64encode(buffer).decode('utf-8')
        
        # 保存检测记录
        detection = ObjectDetection(
            image_path=upload_path,
            result_path=result_path,
            object_count=len(result.boxes),
            detection_data=json.dumps(detection_info)
        )
        
        db.session.add(detection)
        db.session.commit()
        
        return api_response(
            data={
                "detection_id": detection.id,
                "result_image": f"data:image/jpeg;base64,{result_base64}",
                "object_count": detection.object_count,
                "detection_data": detection_info
            },
            code=200
        )
    except Exception as e:
        db.session.rollback()
        return api_response(message=str(e), code=500, status_code=500)

@detection_bp.route('/history/<int:detection_id>', methods=['GET'])
def get_detection_detail(detection_id):
    """
    获取目标检测历史详情
    ---
    tags:
      - 目标检测
    parameters:
      - name: detection_id
        in: path
        type: integer
        required: true
        description: 检测记录ID
    responses:
      200:
        description: 获取成功
        schema:
          type: object
          properties:
            code:
              type: integer
              example: a200
            data:
              type: object
              properties:
                detection_id:
                  type: integer
                  description: 检测ID
                timestamp:
                  type: string
                  description: 检测时间
                result_image:
                  type: string
                  description: 检测结果图片(Base64)
                object_count:
                  type: integer
                  description: 检测到的对象数量
                detection_data:
                  type: object
                  description: 详细检测数据
      404:
        description: 记录不存在
      500:
        description: 服务器内部错误
    """
    try:
        record = ObjectDetection.query.get(detection_id)
        if not record:
            return api_response(message="记录不存在", code=404, status_code=404)
            
        # 读取结果图片
        with open(record.result_path, "rb") as img_file:
            result_base64 = base64.b64encode(img_file.read()).decode('utf-8')
            
        # 解析检测数据
        detection_data = json.loads(record.detection_data)
        
        # 如果是旧数据没有中文名称，转换一下
        if 'original_names' not in detection_data and 'class_names' in detection_data:
            english_names = detection_data['class_names']
            detection_data['class_names'] = [current_app.config['YOLO_CLASS_MAPPING'].get(name, name) 
                                           for name in english_names]
            detection_data['original_names'] = english_names
            
        return api_response(
            data={
                "detection_id": record.id,
                "timestamp": record.timestamp.isoformat(),
                "result_image": f"data:image/jpeg;base64,{result_base64}",
                "object_count": record.object_count,
                "detection_data": detection_data
            },
            code=200
        )
    except Exception as e:
        return api_response(message=str(e), code=500, status_code=500) 